#include "tape.h"
#include <stdlib.h>

Tape::Tape(void)
{
	m_size = 0;
	m_bBuffer = NULL;
	m_len = 0;
}

Tape::Tape(DWORD initSize)
{
	m_size = __max(4, initSize);
	m_bBuffer = new BYTE[m_size];
	memset(m_bBuffer, 0x00, m_size);
	m_len = 0;
}

Tape::~Tape()
{
	if(m_size != 0) {
		delete[] m_bBuffer;
	}
}

void Tape::_EnsureSize(DWORD needSize, DWORD grainSize)
{
	if(m_size < needSize) {
		DWORD extSize = ((needSize-1) / grainSize + 1) * grainSize;
		BYTE* extBuffer = new BYTE[extSize];
		memset(extBuffer, 0x00, extSize);
		if(m_size != 0) {
			if(m_len != 0) {
				memcpy_s(extBuffer, extSize, m_bBuffer, m_len);
			}
			delete m_bBuffer;
		}
		m_size = extSize;
		m_bBuffer = extBuffer;
	}
}

BOOL Tape::Copy(Tape* paTape)
{
	DWORD newLen = paTape->m_len;
	if (newLen > 0) {
		_EnsureSize(newLen);

		memcpy_s(m_bBuffer, m_size, paTape->m_bBuffer, newLen);
		m_len = newLen;
		return(TRUE);
	}
	else {
		m_len = 0;
		return(FALSE);
	}
}

BOOL Tape::Append(Tape* paTape)
{
	DWORD moreLen = paTape->m_len;
	if (moreLen > 0) {
		_EnsureSize(m_len + moreLen);

		memcpy_s(m_bBuffer + m_len, moreLen, paTape->m_bBuffer, moreLen);
		m_len += moreLen;
		return(TRUE);
	}
	else {
		m_len = 0;
		return(FALSE);
	}
}

DWORD Tape::Export(void* pDstCache, DWORD dstSize)
{
	if((m_size == 0) || (m_len > dstSize)) {
		return(0);
	}
	
	if (m_len > 0) {
		memcpy_s(pDstCache, dstSize, m_bBuffer, m_len);
	}
	return(m_len);
}

DWORD Tape::Import(const void* pSrcCache, DWORD len)
{
	if (len > 0) {
		_EnsureSize(len);

		memcpy_s(m_bBuffer, m_size, pSrcCache, len);
		m_len = len;
	}
	else {
		m_len = 0;
	}
	return(m_len);
}

DWORD Tape::Append(const void* pSrcCache, DWORD len)
{
	if (len > 0) {
		_EnsureSize(m_len + len);

		memcpy_s(m_bBuffer + m_len, m_size - m_len, pSrcCache, len);
		m_len += len;
	}
	return(m_len);
}

DWORD Tape::ImportN(const void* pSrcNcache)
{
	Ntype nt;
	memcpy_s(&nt, 4, pSrcNcache, 4);
	_EnsureSize(nt.length);

	memcpy_s(m_bBuffer, m_size, pSrcNcache, nt.length);
	m_len = nt.length;
	return(m_len);
}

DWORD Tape::AppendN(const void* pSrcNcache)
{
	Ntype nt;
	memcpy_s(&nt, 4, pSrcNcache, 4);
	_EnsureSize(m_len + nt.length);

	memcpy_s(m_bBuffer + m_len, m_size - m_len, pSrcNcache, nt.length);
	m_len += nt.length;
	return(m_len);
}
